package com.register.client.start;

import cn.hutool.core.lang.UUID;
import com.register.client.domian.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.annotation.PreDestroy;
import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * 服务启动时,
 * 启动新的线程
 * 负责和server进行通信
 * 并持续的发送心跳建立连接
 */
@Component
@Order(1)
public class RegisterClient implements ApplicationRunner {

    public static final Logger log = LoggerFactory.getLogger(RegisterClient.class);

    public static final Long HEAR_BEAT_TIME = 15 * 1000L;
    /**
     * @param args
     * @throws Exception
     */
    @Autowired
    private ServerInfomation serverInfomation;

    @Autowired
    private RegisterRequest registerRequest;

    @Autowired
    private HttpSender httpSender;

    /**
     * 服务是否存活
     */
    private Boolean isRunning;
    /**
     * 服务启动时,执行逻辑代码
     * @param args
     * @throws Exception
     */
    @Override
    public void run(ApplicationArguments args) throws Exception {

        //后期使用构造器模式 慢慢优化
        //1.获取本机ip地址
        String ip = getOwnerIpAddr();
        String hostName = getOwnerHostName();
        registerRequest.setIp(ip);
        registerRequest.setHostName(hostName);
        registerRequest.setServiceInstanceId(UUID.randomUUID().toString());
        RegisterWorker registerWorker = new RegisterWorker(
                httpSender,
                registerRequest,
                serverInfomation);
        //启动注册服务线程
        registerWorker.start();

        //启动拉取全量注册表线程和增量注册表线程
        new ClientCachedServiceRegistry(this).initialize();



    }


    /**
     * 服务关闭时,给server发送消息,去除服务
     */
    @PreDestroy
    public void destory() {
        httpSender.noticeServerMoveInstance(registerRequest);
    }

    /**
     * 获取本机地址
     * @return
     * @throws UnknownHostException
     */
    private String getOwnerIpAddr() throws UnknownHostException {
        //String IP = InetAddress.getLocalHost().getHostAddress();
        InetAddress address = InetAddress.getLocalHost();
        return address.getHostAddress(); //返回IP地址
    }

    /**
     * 获取主机名
     *
     * @return
     * @throws UnknownHostException
     */
    private String getOwnerHostName() throws UnknownHostException {
        //String IP = InetAddress.getLocalHost().getHostAddress();
        InetAddress address = InetAddress.getLocalHost();
        return address.getHostName(); //返回hostName;
    }

    /**
     * 采用内部类的方式构建
     */
    private class RegisterWorker extends Thread {

        public final Logger log = LoggerFactory.getLogger(RegisterWorker.class);

        private HttpSender httpSender;

        private RegisterRequest registerRequest;

        private ServerInfomation serverInfomation;

        private Boolean finishedRegister;

        public RegisterWorker(
                HttpSender httpSender,
                RegisterRequest registerRequest,
                ServerInfomation serverInfomation

        ) {
            this.httpSender = httpSender;
            this.registerRequest = registerRequest;
            this.serverInfomation = serverInfomation;
            this.finishedRegister = false;

        }

        @Override
        public void run() {
            if (!finishedRegister) {
                log.info("服务[{}]尝试开始注册", registerRequest.getServiceName());
                Response response = httpSender.register(registerRequest);
                log.info("服务注册的结果是:{}", response.getCode());

                if (response.getCode().equals(Response.SUCCESS.getCode())) {
                    finishedRegister = true;
                } else {
                    log.error("{}服务注册失败", registerRequest.getServiceName());
                    return;
                }
            }
            //注册成功后
            if (finishedRegister) {
                HeartBeat heartBeat = new HeartBeat(registerRequest.getServiceName(), registerRequest.getServiceInstanceId());
                while (true) {
                    //每隔30秒发送心跳,检查当前的serviceInstanceId是否存在
                    try {
                        Thread.sleep(HEAR_BEAT_TIME);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    //发送心跳
                    log.info("服务实例[{}] 正在发送心跳", registerRequest.getServiceInstanceId());
                    Response response = httpSender.heartBeat(heartBeat);
                    if (response.getCode().equals(Response.FAILE.getCode())) {
                        log.info("服务实例[{}] 请求心跳失败", registerRequest.getServiceInstanceId());
                    }
                    log.info("服务实例[{}] 请求心跳成功", registerRequest.getServiceInstanceId());
                }
            }
        }
    }
}
